#include<muduo/net/TcpClient.h>
#include<muduo/net/EventLoop.h>
#include<muduo/net/EventLoopThread.h>
#include<string>
#include<iostream>
#include<memory>
#include<unistd.h>

class TcpClient
{
public:
    TcpClient(const std::string& serverIP, const uint16_t port, const std::string& name)
        : _client(new muduo::net::TcpClient(_loopThread.startLoop(), muduo::net::InetAddress(serverIP, port), name))
        , _loopThread(nullptr)
        {}
    
    bool init(const muduo::net::ConnectionCallback& conn_cb, const muduo::net::MessageCallback& mess_cb)
    {
        if (_client)
        {
            _client->setConnectionCallback(conn_cb);
            _client->setMessageCallback(mess_cb);
            return true;
        }
        return false;
    }

    void connect()
    {
        _client->connect();
    }

private:
    muduo::net::EventLoopThread _loopThread;
    std::unique_ptr<muduo::net::TcpClient> _client;
};

class EchoClient : public TcpClient
{
public:
    EchoClient(const std::string& serverIP, const uint16_t port, const std::string& name = "Client")
        :TcpClient(serverIP, port, name)
    {}

    void onConnected(const muduo::net::TcpConnectionPtr& conn)
    {
        if (conn->connected())
        {
            _conn = conn;
            std::cout << "连接服务端：" << conn->getTcpInfoString() << "成功！" << std::endl;
        }
    }

    void onMessageCallback(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buffer, muduo::Timestamp)
    {
        std::cout << "服务端返回：>" << buffer->retrieveAllAsString() << std::endl;
    }

    void send(const std::string& data)
    {
        if (_conn->connected())
        {
            _conn->send(data);
        }
    }
private:
    muduo::net::TcpConnectionPtr _conn;
};

int main()
{
    EchoClient Echo("127.0.0.1", 9090);
    Echo.init(std::bind(&EchoClient::onConnected, &Echo, std::placeholders::_1),
            std::bind(&EchoClient::onMessageCallback, &Echo, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

    Echo.connect();

    while (1)
    {
        std::string in;
        std::cout << "输入：>";
        std::getline(std::cin, in);
        Echo.send(in);
    }
    return 0;
}